const Core = require('@alicloud/pop-core');

const {
    Device,
    HeartRateDetail,
    HeartRateMeasure,
    SleepDetail,
    Temperature,
    HRV,
    StepDetail,
    StepPerDay,
    addForeignKey,
    Gateway
} = require('./index')
addForeignKey()

const deviceIdMap = {

}

async function getGatewayTime(name) {
    let dev = await Gateway.findOne({ where: { name: name } })
    if (dev) {
        // new Date(dev.updatedAt).getTime()
        if (dev.updatedAt) {
            return new Date(dev.updatedAt).getTime()
        } else {
            return new Date('2021-01-01').getTime()
        }
    } else {
        dev = await Gateway.create({ name, type: 1 })
        return new Date('2021-01-01').getTime()
    }
}

async function updateGatewayTime(name, time) {
    let dev = await Gateway.findOne({ where: { name: name } })
    if (dev) {
        dev.updatedAt = time
        dev.save()
    }
}

async function getDeviceId(mac) {
    let dev = await Device.findOne({ where: { mac: mac } })
    if (dev) {
        return dev.id
    } else {
        dev = await Device.create({ mac, type: 1 })
        return dev.id
    }
}

async function create(model, record) {
    try {
        let res = await model.create(record)
        return true
    } catch (e) {
        if (e && e.original && e.original.code === 'ER_DUP_ENTRY') {
            console.log(`ER_DUP_ENTRY, retrying...`)
        } else {
            console.log(e)
        }
        return false
    }
}

var client = new Core({
    accessKeyId: 'LTAI5tFWhsn43B4zchSz4EkJ',
    accessKeySecret: '5rYnMECRrUBuoUPDLBxVgmgyl9huXN',
    endpoint: 'https://iot.cn-shanghai.aliyuncs.com',
    apiVersion: '2018-01-20'
});

async function QueryDevicePropertyData() {

    var params = {
        "RegionId": "cn-shanghai",
        "ProductKey": "gemsAnScqtP",
        "DeviceName": "test8",
        "IotInstanceId": "iot-060a093d",
        "Identifier": "id",
        "StartTime": 1643368781699,
        "EndTime": 1743368781699,
        "PageSize": 100,
        "Asc": 1
    }

    var requestOption = {
        method: 'POST'
    };

    client.request('QueryDevicePropertyData', params, requestOption).then((result) => {
        //   console.log(JSON.stringify(result));
        /*
        [Object: null prototype] {
        RequestId: 'F46471B8-D227-54F6-BE67-F85A1C1496F4',
        Data: [Object: null prototype] {
            NextValid: true,
            NextTime: 1643368904185,
            List: [Object: null prototype] { PropertyInfo: [Array] }
        },
        Code: '',
        Success: true
        }
        */
        console.log(result.Data.List.PropertyInfo.length);
        let start = result.Data.List.PropertyInfo[0].Time
        let end = result.Data.List.PropertyInfo[result.Data.List.PropertyInfo.length - 1].Time
        QueryDevicePropertiesData(start, end)
    }, (ex) => {
        console.log(ex);
    })
}

async function QueryDevicePropertiesData(dev, start, end) {
    console.log(QueryDevicePropertiesData, dev, new Date(start), new Date(end))
    let identifiers = ["id", "temperature", "hrv", "singleHeartRate", "heartRate", "sleepDetails", "stepsDetails", "stepsPerDay"]
    var params = {
        "RegionId": "cn-shanghai",
        "ProductKey": "gemsAnScqtP",
        "DeviceName": dev,
        "IotInstanceId": "iot-060a093d",
        "Identifier": identifiers,
        "StartTime": start,
        "EndTime": end,
        "PageSize": 100,
        "Asc": 1
    }

    var requestOption = {
        method: 'POST'
    };

    let result = await client.request('QueryDevicePropertiesData', params, requestOption)
    // result = JSON.stringify(result)
    console.log(result);
    if (!result.Success) {
        return false
    }
    /*
    [Object: null prototype] {
      NextValid: true,
      NextTime: 1643368853690,
      RequestId: '656596AD-5EC9-548D-9925-53DF58DBDA4F',
      PropertyDataInfos: [Object: null prototype] {
        PropertyDataInfo: [
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype],
          [Object: null prototype]
        ]
      },
      Code: '',
      Success: true
    }
    */
    let array = result.PropertyDataInfos.PropertyDataInfo
    console.log(array);
    let mapTimestamp = {}
    for (let i = 0; i < array.length; i++) {
        const element = array[i];
        if (element.Identifier == 'id') {
            let records = element.List.PropertyInfo
            for (let j = 0; j < records.length; j++) {
                const mac = records[j].Value;
                const timestamp = records[j].Time;
                mapTimestamp[timestamp] = mac
            }
            result.count = records.length
        }
    }
    for (let i = 0; i < array.length; i++) {
        const element = array[i];
        console.log(element.Identifier, element.List.PropertyInfo.length);
        let records = element.List.PropertyInfo
        for (let j = 0; j < records.length; j++) {
            const value = records[j].Value;
            const timestamp = records[j].Time;
            let mac = mapTimestamp[timestamp]
            let id = deviceIdMap[mac]
            if (!id) {
                id = await getDeviceId(mac)
                deviceIdMap[mac] = id
            }
            /*
            [Object: null prototype] {
                Value: '[{"date":1638763379000,"data":"[63,0,0,0,0,0,0,0,0,0,0,0,0,0,0]","id":0}]',
                Time: 1643369019512
            }
            */
            if (element.Identifier == 'heartRate') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await HeartRateDetail.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await HeartRateDetail.create({ dev_id: id, data: data.data, date: data.date })
                    }
                }
            } else if (element.Identifier == 'singleHeartRate') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await HeartRateMeasure.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await HeartRateMeasure.create({ dev_id: id, data: data.hr, date: data.date })
                    }
                }
            } else if (element.Identifier == 'temperature') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await Temperature.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await Temperature.create({ dev_id: id, data: data.temp, date: data.date })
                    }
                }
            } else if (element.Identifier == 'hrv') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await HRV.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await HRV.create({ dev_id: id, pressure: data.pressure, hrv: data.hrv, date: data.date })
                    }
                }
            } else if (element.Identifier == 'sleepDetails') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await SleepDetail.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await SleepDetail.create({ dev_id: id, data: data.data, date: data.date })
                    }
                }
            } else if (element.Identifier == 'stepsDetails') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await StepDetail.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await StepDetail.create({ dev_id: id, data: data.details, kcal: data.kcal, distance: data.distance, steps: data.steps, date: data.date })
                    }
                }
            } else if (element.Identifier == 'stepsPerDay') {
                // console.log(data)
                let json = JSON.parse(value)
                for (let k = 0; k < json.length; k++) {
                    const data = json[k];
                    let record = await StepPerDay.findOne({ where: { dev_id: id, date: data.date } })
                    if (record) {

                    } else {
                        record = await StepPerDay.create({ dev_id: id, sportTime: data.sportTime, fastSportTime: data.fastSportTime, kcal: data.kcal, distance: data.distance, steps: data.steps, target: data.target, date: data.date })
                    }
                }
            }
        }
        // ["id", "temperature", "hrv", "singleHeartRate", "heartRate", "sleepDetails", "stepsDetails", "stepsPerDay"]
    }
    if (result.NextValid && result.NextTime) {
        await updateGatewayTime(dev, result.NextTime)
    }
    return result.NextValid && result.count == 100
}

async function sleep(ms) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve()
        }, ms)
    })
}

// QueryDevicePropertyData()
async function loadData() {
    const devList = ["test8","test9"]
    for (let i = 0; i < devList.length; i++) {
        const name = devList[i];
        let newData = true
        while (newData) {
            try {
                let start = await getGatewayTime(name)
                let end = new Date('2022-01-29').getTime()
                // let end = Date.now()
                console.log('loadData', name, start, end)
                newData = await QueryDevicePropertiesData(name, start, end)
            } catch (error) {
                console.log(error)
                await sleep(1000)
            }
        }
    }
}

loadData()
